﻿using System;
using System.Collections; 
using System.Collections.Generic;

using System.Text;
using System.IO; 

namespace Parseq.Util
{
    class Buffer 
    {
        private byte[] inner;
        private int max = 0;
        private int count = 0; 

        public Buffer(int max) {
            this.inner = new byte[max];
            this.max = max; 
        }

        public byte this[int index] {
            get {
                return this.inner[index];
            }
            set {
                this.inner[index] = value; 
            }
        }

        public void ReadStream(Stream s)
        {
            this.count = s.Read(this.inner, 0, this.max);
        }

        public int Count
        {
            get { return this.count; }
        }
    }

    struct BufferIndex
    {
        public int bufferIndex;
        public int offset;
        public BufferIndex(int b, int o)
        {
            bufferIndex = b;
            offset = o; 
        }
    }

    public class BufferList
    {
        private IList<Buffer> list = new List<Buffer>();
        private IList<long> countList = new List<long>(); 
        private long length;
        private int bufferSize = 8192;
        private int bufferCount = 0; 
        
        public BufferList()
        {
            this.countList.Add(0); 
        }

        public bool ReadStream(Stream s)
        {
            Buffer buffer = new Buffer(this.bufferSize);
            buffer.ReadStream(s); 
            if (buffer.Count != 0) // we have data. 
            {
                this.list.Add(buffer);
                this.length += buffer.Count;
                this.countList.Add(this.length);
                this.bufferCount += 1;
                return true;
            }
            else
            {
                return false; 
            }
        }

        private BufferIndex toBufferIndex(long index)
        {
            for (int i = 0; i < this.countList.Count - 1; ++i) {
                if (this.countList[i] <= index && index < this.countList[i + 1])
                {
                    return new BufferIndex(i, (int)(index - this.countList[i])); 
                }
            }
            throw new IndexOutOfRangeException("index outside of the range of the bufferlist\n"); 
        }

        public byte this[long index]
        {
            get
            {
                BufferIndex bIndex = this.toBufferIndex(index);
                return this.list[bIndex.bufferIndex][bIndex.offset];
            }
            set
            {
                BufferIndex bIndex = this.toBufferIndex(index);
                this.list[bIndex.bufferIndex][bIndex.offset] = value; 
            }
        }

        public long Length
        {
            get { return this.length; }
        }
    }


}
